package com.example.music.viewmodel

import android.app.Application
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope
import com.example.music.data.Music
import com.example.music.data.PlaybackState
import com.example.music.data.RepeatMode
import com.example.music.data.ShuffleMode
import com.example.music.player.MusicPlayerService
import com.example.music.repository.MusicRepository
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class MusicViewModel(application: Application) : AndroidViewModel(application) {
    
    private val repository = MusicRepository(application)
    private var musicPlayerService: MusicPlayerService? = null
    private var isServiceBound = false
    
    private val _musicList = MutableLiveData<List<Music>>()
    val musicList: LiveData<List<Music>> = _musicList
    
    private val _currentMusic = MutableLiveData<Music?>()
    val currentMusic: LiveData<Music?> = _currentMusic
    
    private val _playbackState = MutableLiveData(PlaybackState.STOPPED)
    val playbackState: LiveData<PlaybackState> = _playbackState
    
    private val _currentPosition = MutableLiveData(0L)
    val currentPosition: LiveData<Long> = _currentPosition
    
    private val _duration = MutableLiveData(0L)
    val duration: LiveData<Long> = _duration
    
    private val _isLoading = MutableLiveData(false)
    val isLoading: LiveData<Boolean> = _isLoading
    
    private var positionUpdateJob: Job? = null
    
    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            val binder = service as MusicPlayerService.MusicPlayerBinder
            musicPlayerService = binder.getService()
            isServiceBound = true
            musicPlayerService?.setMusicList(_musicList.value ?: emptyList())
            observePlayerState()
        }
        
        override fun onServiceDisconnected(name: ComponentName?) {
            isServiceBound = false
            musicPlayerService = null
        }
    }
    
    init {
        viewModelScope.launch {
            _isLoading.value = true
            loadMusic()
            bindService()
            _isLoading.value = false
        }
    }
    
    private fun bindService() {
        Intent(getApplication(), MusicPlayerService::class.java).also { intent ->
            getApplication<Application>().bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }
    
    private suspend fun loadMusic() {
        _musicList.value = repository.getAllMusic()
    }
    
    private fun observePlayerState() {
        musicPlayerService?.exoPlayer?.addListener(object : androidx.media3.common.Player.Listener {
            override fun onIsPlayingChanged(isPlaying: Boolean) {
                _playbackState.value = if (isPlaying) PlaybackState.PLAYING else PlaybackState.PAUSED
                if (isPlaying) startPositionUpdates() else stopPositionUpdates()
            }
            
            override fun onMediaItemTransition(mediaItem: androidx.media3.common.MediaItem?, reason: Int) {
                super.onMediaItemTransition(mediaItem, reason)
                mediaItem?.mediaId?.toLongOrNull()?.let { id ->
                    _currentMusic.value = _musicList.value?.find { it.id == id }
                }
                _duration.value = musicPlayerService?.exoPlayer?.duration ?: 0L
                _currentPosition.value = musicPlayerService?.exoPlayer?.currentPosition ?: 0L
            }
            
            override fun onPlaybackStateChanged(playbackState: Int) {
                super.onPlaybackStateChanged(playbackState)
                when (playbackState) {
                    androidx.media3.common.Player.STATE_BUFFERING -> _playbackState.value = PlaybackState.STOPPED
                    androidx.media3.common.Player.STATE_READY -> {
                        _playbackState.value = if (musicPlayerService?.exoPlayer?.isPlaying == true) PlaybackState.PLAYING else PlaybackState.PAUSED
                        _duration.value = musicPlayerService?.exoPlayer?.duration ?: 0L
                    }
                    androidx.media3.common.Player.STATE_ENDED -> {
                        _playbackState.value = PlaybackState.STOPPED
                        _currentPosition.value = 0L
                    }
                    else -> _playbackState.value = PlaybackState.STOPPED
                }
            }
        })
    }
    
    private fun startPositionUpdates() {
        positionUpdateJob?.cancel()
        positionUpdateJob = viewModelScope.launch {
            while (true) {
                _currentPosition.value = musicPlayerService?.exoPlayer?.currentPosition ?: 0L
                delay(1000) // Update every second
            }
        }
    }
    
    private fun stopPositionUpdates() {
        positionUpdateJob?.cancel()
        positionUpdateJob = null
    }
    
    fun playMusic(music: Music) {
        musicPlayerService?.playMusic(music)
        _currentMusic.value = music
    }
    
    fun play() {
        musicPlayerService?.play()
    }
    
    fun pause() {
        musicPlayerService?.pause()
    }
    
    fun playNext() {
        musicPlayerService?.exoPlayer?.seekToNextMediaItem()
    }
    
    fun playPrevious() {
        musicPlayerService?.exoPlayer?.seekToPreviousMediaItem()
    }
    
    fun seekTo(position: Long) {
        musicPlayerService?.seekTo(position)
    }
    
    fun setRepeatMode(mode: RepeatMode) {
        musicPlayerService?.setRepeatMode(mode)
    }
    
    fun setShuffleMode(mode: ShuffleMode) {
        musicPlayerService?.setShuffleMode(mode)
    }
    
    fun searchMusic(query: String) {
        viewModelScope.launch {
            _isLoading.value = true
            val results = repository.searchMusic(query)
            _musicList.value = results
            musicPlayerService?.setMusicList(results)
            _isLoading.value = false
        }
    }
    
    fun addOnlineMusic(url: String) {
        viewModelScope.launch {
            try {
                val onlineMusic = Music(
                    id = System.currentTimeMillis(),
                    title = "在线音乐",
                    artist = "未知艺术家",
                    album = "在线专辑",
                    duration = 0L,
                    uri = android.net.Uri.parse(url),
                    size = 0L,
                    dateAdded = System.currentTimeMillis()
                )
                
                val currentList = (_musicList.value ?: emptyList()).toMutableList()
                currentList.add(0, onlineMusic)
                _musicList.value = currentList
                
                musicPlayerService?.setMusicList(currentList)
            } catch (e: Exception) {
                // Handle error
            }
        }
    }
    
    override fun onCleared() {
        super.onCleared()
        if (isServiceBound) {
            getApplication<Application>().unbindService(serviceConnection)
            isServiceBound = false
        }
        stopPositionUpdates()
    }
}